package com.smartleanx.module.hrm.framework.excelUtil.handler;

import java.util.List;

import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddress;

import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.write.handler.CellWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteTableHolder;

/**
 * 自定义单元格合并 Handler
 *
 * @author yanglihao
 */
public class CustomCellMergeHandler implements CellWriteHandler {

    private int[] mergeColumnIndex;
    private int mergeRowIndex;

    public CustomCellMergeHandler() {}

    /**
     * 构造函数
     * 
     * @param mergeColumnIndex 要合并的列索引数组
     * @param mergeRowIndex 合并开始的行索引
     */
    public CustomCellMergeHandler(int[] mergeColumnIndex, int mergeRowIndex) {
        this.mergeColumnIndex = mergeColumnIndex;
        this.mergeRowIndex = mergeRowIndex;
    }

    @Override
    public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder,
        List<WriteCellData<?>> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
        // 当前行索引
        int curRowIndex = cell.getRowIndex();
        // 当前列索引
        int curColIndex = cell.getColumnIndex();
        // 如果当前行大于合并开始行
        if (curRowIndex > mergeRowIndex) {
            // 当前列在需要合并的列中
            for (int columnIndex : mergeColumnIndex) {
                if (columnIndex == curColIndex) {
                    // 进行合并操作
                    mergeWithPrevRow(writeSheetHolder, cell, curRowIndex, curColIndex);
                }
            }
        }
    }

    /**
     * 当前单元格向上合并
     * 
     * @param writeSheetHolder 当前工作表
     * @param cell 当前单元格
     * @param curRowIndex 当前行索引
     * @param curColIndex 当前列索引
     */
    private void mergeWithPrevRow(WriteSheetHolder writeSheetHolder, Cell cell, int curRowIndex, int curColIndex) {
        // 获取当前单元格的数据
        // Object curData = cell.getCellType() == CellType.STRING ? cell.getStringCellValue() : cell.getNumericCellValue();
        String curKey = cell.getSheet().getRow(curRowIndex).getCell(0).getStringCellValue();
        // 获取前一个单元格的数据
        // Cell preCell = cell.getSheet().getRow(curRowIndex - 1).getCell(curColIndex);
        // Object preData = preCell.getCellType() == CellType.STRING ? cell.getStringCellValue() : cell.getNumericCellValue();
        String preKey = cell.getSheet().getRow(curRowIndex - 1).getCell(0).getStringCellValue();

        // 判断当前单元格和前一个单元格的数据以及主键是否相同
        // if (curData.equals(preData) && curKey.equals(preKey)) {
        if (curKey.equals(preKey)) {
            // 获取工作表
            Sheet sheet = writeSheetHolder.getSheet();
            // 获取已合并的区域
            List<CellRangeAddress> mergedRegions = sheet.getMergedRegions();
            boolean isMerged = false;
            // 检查前一个单元格是否已经被合并
            for (int i = 0; i < mergedRegions.size() && !isMerged; i++) {
                CellRangeAddress cellRangeAddr = mergedRegions.get(i);
                // 若上一个单元格已经被合并，则先移出原有的合并单元，再重新添加合并单元
                if (cellRangeAddr.isInRange(curRowIndex - 1, curColIndex)) {
                    sheet.removeMergedRegion(i);
                    cellRangeAddr.setLastRow(curRowIndex);
                    sheet.addMergedRegion(cellRangeAddr);
                    isMerged = true;
                }
            }
            // 如果前一个单元格未被合并，则新增合并区域
            if (!isMerged) {
                CellRangeAddress cellRangeAddress = new CellRangeAddress(curRowIndex - 1, curRowIndex, curColIndex, curColIndex);
                sheet.addMergedRegion(cellRangeAddress);
            }
        }
    }

    @Override
    public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row,
        Head head, Integer columnIndex, Integer relativeRowIndex, Boolean isHead) {}

    @Override
    public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell,
        Head head, Integer relativeRowIndex, Boolean isHead) {}
}
